package web.controllers;

import java.io.BufferedInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import javax.ws.rs.core.Context;

import map.beans.EmpConfigManagerBean;
import map.beans.EmpMapVersionBean;
import map.beans.EmpResponseBean;
import map.beans.GitVersionBean;
import map.beans.MapEngineRegistrationBean;
import map.beans.MapToolConfigBean;
import map.beans.OwfLibLocationBean;
import map.beans.WmsServerBean;
import map.constants.MapDefaultPropertyValues;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

import web.dao.interfaces.MapConfigurationServiceInterface;
import web.service.interfaces.EngineRegistrationServiceInterface;

@Controller
@RequestMapping("admin/mapengine/config")
public class MapEngineConfigController {
	public static final Logger LOGGER = Logger.getLogger(MapEngineConfigController.class.getName());

	@Autowired
	private MapConfigurationServiceInterface mapConfigService;	
	@Autowired
	private EngineRegistrationServiceInterface mapEngineRegistrationService;	
	@Autowired
	ServletContext ctx;
	

	/**
	 * @return {@link String}
	 * @throws IOException
	 */
	@RequestMapping(value = "/getOwfLocation", method = { RequestMethod.GET })
	@ResponseBody
	public final String getOwfLocation() throws IOException {		
		String owfLocation = "";
		try {
			owfLocation = mapConfigService.getOwfJsLocation();
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
		}
		return owfLocation;
	}	
	
	@RequestMapping(value = "/update/owfLibLocation", method = RequestMethod.POST)
	@ResponseBody 
	public void updateOwfLibLocation(@Context HttpServletResponse response, @Valid @ModelAttribute(value = "OwfLibLocationBean") OwfLibLocationBean owf, BindingResult result) {
	// public void updateOwfLibLocation(@Context HttpServletResponse response, @RequestParam String owfLibLoc) {	
		if (owf.getLibLocation().equals("") || owf == null) {
			owf.setLibLocation(MapDefaultPropertyValues.OWF_WIDGET_JS);
			owf.setId(null);
		}
		
		int code = -1;
		if (this.mapConfigService.updateOwfJsLocation(owf)) {
			code = HttpServletResponse.SC_OK;;
		} else {
			code = HttpServletResponse.SC_BAD_REQUEST;
		}		
		
		response.setContentType("text/plain");
		response.setStatus(code);
		
		try {
			response.getOutputStream().write(owf.getLibLocation().getBytes(), 0, owf.getLibLocation().length());
		} catch (IOException e) {
			LOGGER.log(Level.WARNING, e.getMessage());
		}			
	}	
	

	/**
	 * @return {@link String}
	 */
	@RequestMapping(value = "/getWmsServerUrls", method = RequestMethod.GET, produces="application/json")
	@ResponseBody
	public List<WmsServerBean> getWmsServerUrls() {
		List<WmsServerBean> config = null;
		try {
			config = mapConfigService.getWmsServerUrls();
			
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
        }		
		return config;
    }
	
	/** 
	 * @return 
	 */
	@RequestMapping(value = "/getMapTools", method = RequestMethod.GET, produces="application/json")
	@ResponseBody
	public List<MapToolConfigBean> getMapTools() {
		List<MapToolConfigBean> registeredTools = new ArrayList<MapToolConfigBean>();

		try {
			registeredTools = this.mapConfigService.getMapTools();			
			
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
        }		
		
		return registeredTools;
    }
	
	/** 
	 * @return {@link EmpMapVersionBean}
	 */
	@RequestMapping(value = "/getMapInformation", method = RequestMethod.GET, produces="application/json")
	@ResponseBody
	public GitVersionBean getMapInformation() {
		GitVersionBean mapInfo = null;
		
		try {
			mapInfo = this.mapConfigService.getEmpVersionInformation();			
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
        }			
		return mapInfo;
    }	
	
	/** 
	 * @return {@link EmpMapVersionBean}
	 */
	@RequestMapping(value = "/getMapEngines", method = RequestMethod.GET, produces="application/json")
	@ResponseBody
	public List<MapEngineRegistrationBean> getMapEngines() {						
		return this.mapConfigService.getMapEngines();
    }	
	
	/** 
	 * @return {@link EmpConfigManagerBean}
	 */
	@RequestMapping(value = "/getMapConfiguration", method = RequestMethod.GET, produces="application/json")
	@ResponseBody
	public EmpConfigManagerBean getMapConfig(@Context HttpServletRequest request) {
		EmpConfigManagerBean empConfig = new EmpConfigManagerBean();

		try {
			if (request != null) {
				mapEngineRegistrationService.setServerInfo(request);
			}
			empConfig = this.mapConfigService.getMapConfig();
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
        }
		
		return empConfig;
    }
	
	
	@RequestMapping(value = "/export", method = RequestMethod.GET)
	@ResponseBody
	public void exportData(@Context HttpServletRequest request, @Context HttpServletResponse response) {

		try {			
			response.setContentType("application/json");
			response.setHeader("Content-Disposition", "attachment;filename=" + MapDefaultPropertyValues.EXPORT_DB_NAME + ".json");			
			response.getOutputStream().write(mapConfigService.fectchMapConfigAsJson().getBytes());					
			response.getOutputStream().close();
			response.getOutputStream().flush();			
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
		}
	}
	
	
	@RequestMapping(value = "/import", method = RequestMethod.POST)/*@Context HttpServletRequest request, @RequestParam("fileInput") MultipartFile file) {/*/
	@ResponseBody
	public EmpResponseBean importData(@Context HttpServletRequest request, @Context HttpServletResponse response) {

		EmpResponseBean resp = new EmpResponseBean();		
		try {

			// boolean isMultipart = ServletFileUpload.isMultipartContent(request);
			String content = "";

			FileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
				List<FileItem> items = upload.parseRequest(request);
				Iterator<FileItem> iterator = items.iterator();

				while (iterator.hasNext()) {
					FileItem item = (FileItem) iterator.next();

					if (!item.isFormField()) {
						BufferedInputStream buff = new BufferedInputStream(item.getInputStream());
						byte[] bytes = new byte[buff.available()];
						buff.read(bytes, 0, bytes.length);
						content = new String(bytes);
					}
				}

				if (mapConfigService.persistDataFile(content)) {
					resp.setResult(content);
					resp.setStatus(String.valueOf(HttpServletResponse.SC_OK));
					resp.setMessage("Success");					
				} else {
					resp.setResult(content);
					resp.setStatus(String.valueOf(HttpServletResponse.SC_NO_CONTENT));
					resp.setMessage("failure");
				}

		} catch (FileUploadException e) {
			LOGGER.log(Level.WARNING, e.getMessage());
		} catch (Exception e) {
			LOGGER.log(Level.WARNING, e.getMessage());
		}

		return resp;
	}
}

